package com.jin.webvideo.service;

import com.jin.webvideo.parser.ParseResult;
import com.jin.webvideo.util.consts.ConfigConst;
import com.jin.webvideo.videoCache.CacheExecutor;
import com.jin.webvideo.entity.Cache;
import com.jin.webvideo.util.sys.EncryptUtil;
import com.jin.webvideo.util.sys.SystemUtil;
import com.jin.webvideo.mapper.CacheMapper;
import com.jin.webvideo.videoCache.policy.CacheCondition;
import com.jin.webvideo.videoCache.policy.PolicyParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.beans.Transient;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

@Service
public class CacheService {
    @Autowired
    private CacheExecutor exector;
    @Autowired
    private CacheMapper cacheMapper;
    @Autowired
    private ConfigService configService;

    /**
     * 通过url查找视频缓存
     * @param url
     * @return
     */
    public Cache findCacheByUrl(String url){
        Cache cache = cacheMapper.selectByUrl(url);
        if (null != cache ){
            // 处于新建状态 或者 系统存在该缓存
            if (Cache.STATUS_NEW.equals(cache.getStatus()) || exector.exists(cache)){
                cacheMapper.visited(url);
                return cache;
            }
            del(cache.getUrl());
        }
        return null;
    }

    /**
     * 新建或更新视频缓存
     * @param source
     * @param cache 需要更新/新增的缓存
     */
    public void newCache(String source, Cache cache){
        String cacheKey = cache.formatKey();
        Map<String,String> header = configService.configMapByGroupId(cacheKey);
        exector.submit(source, cache, header);
        Cache temp = cacheMapper.hasCache(cache.getUrl());
        if (null == temp && Cache.STATUS_NEW.equals(cache.getStatus())){
            cacheMapper.insert(cache);
            return;
        }
        cacheMapper.updateCache(cache.getUrl(), Cache.STATUS_NEW, cache.getCacheType(), cache.getParserName());
    }

    public Cache needCache(final ParseResult parseResult, final String url) throws UnsupportedEncodingException {
        // 获取需要缓存的地址信息
        Map<String,String> policy = configService.configMapByGroupId(ConfigConst.CACHEPOLICY_CONFIG);
        if (policy.isEmpty()){
            return null;
        }
        int cacheType = 0;
        CacheCondition cacheAll = PolicyParser.parse(policy.getOrDefault(ConfigConst.ATTR_CONFIG_CACHEALL, ConfigConst.CONFIG_EMPTY));
        // 不需要全部缓存
        if (cacheAll.compute(parseResult)){
            cacheType = Cache.TYPE_ALL;
        }
        else{
            CacheCondition cacheIndex = PolicyParser.parse(policy.getOrDefault(ConfigConst.ATTR_CONFIG_CACHEINDEX, ConfigConst.CONFIG_EMPTY));
            if (cacheIndex.compute(parseResult)){
                cacheType = Cache.TYPE_ONLY_INDEX;
            }
        }
        if (cacheType == 0){
            return null;
        }
        // 查询历史缓存记录
        Cache cache = createCache(url, parseResult.getRelURL());
        cache.setCacheType(cacheType);
        cache.setParserName(parseResult.getName());
        return cache;
    }
    public void m3u8Cache(String url){
        Cache cache = cacheMapper.selectByUrl(url);
        if (cache !=null && !Cache.STATUS_CANPLAY.equals(cache.getStatus()) ){
            cacheMapper.updateStatus(url, Cache.STATUS_CACHING);
        }
    }
    public void canPlay(String url) throws IOException {
        Cache cache = cacheMapper.selectByUrl(url);
        long size = SystemUtil.fileSize(exector.cacheLocation(cache));
        if ( !exector.allocated(size) ){
            throw new IOException("空间不足");
        }
        cacheMapper.canPlay(url, size);
    }

    public void del(String url){
        Cache cache = cacheMapper.selectByUrl(url);
        String path = exector.cacheLocation(cache);
        SystemUtil.deleteFile(new File(path));
        cacheMapper.updateStatus(url, Cache.STATUS_DEL);
    }
    public String createVisitedPath(Cache cache){
        return exector.visitedUrl(cache);
    }
    public Cache createCache(String standardizedUrl, String realURL) throws UnsupportedEncodingException {
        // 查询历史缓存记录
        Cache cache = cacheMapper.hasCache(standardizedUrl);
        // 不存在缓存记录， 则新建记录
        if (null == cache){
            String location = createLocation(standardizedUrl);
            cache = Cache.newInstance(realURL, standardizedUrl, location);
        }
        return cache;
    }
    private String createLocation(String url) throws UnsupportedEncodingException {
        String location = EncryptUtil.base64Encrypt(url + System.currentTimeMillis());
        if ( 1 == cacheMapper.hasLocation(location) ){
            return createLocation( location + System.currentTimeMillis());
        }
        return EncryptUtil.md5Hex(location);
    }
}
